home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacHack 1994
/
MacHack 1994.toast
/
MacHack™94
/
Talks & Papers
/
Timothy Knox
/
yerk 3.66
/
Float source
/
fpi⁄o
< prev
next >
Wrap
Text File
|
1994-06-24
|
7KB
|
201 lines
\ FPI/O -- floating-point I/O support for 68000 SANE engine.
\ 5/11/85 ssg Version 1.0
\ 9/26/85 cbd Modified for float heap, removed minor methods
\ 2/07/86 gdc Added words atof and f.r, changed eprint to eprint, printxyz
\ 8/16/86 cdn Eliminated finit & Stringer shorten
\ 5/26/91 rfl Eliminated Stringer class altogether.
\ 10/26/91 rfl abs in front of /mod
\ 12/17/92 rfl fixed a few problems that might occur due to not locking handles
\ 01/26/93 rfl protect parse: to reject a possible float if 2 decimal points are mistakenly
\ adjacent. The case of " 1.234.56" is interpreted as an integer
\ 12/03/93 rfl fixed problem with non FPU machines returning garbage exp when
\ 0 is passed to num2dec in float2dec:. Thanks to Harry Haddon.
\ Removed 2 bytes scratch -use pad instead. Removed if true else false
\ 12/05/93 rfl Rewrote much of the formatting routines and added ability to
\ get addr len of format on stack. More use of pack7 utilities.
Decimal
\ Some useful constants
256 constant neg
0 constant pos
256 constant FixedDecimal
0 constant FloatDecimal
0 value topxyz \ top of string being converted to float
0 variable valid? \ used for scan: but never used otherwise...mhore
\ reentrant code to get rid of leading zeros - not used here
\ : endZ ( addr -- addr) dup c@ ascii 0 = IF 1+ endZ THEN ;
:CLASS FPI/O <Super Object
\ SANE Record Decimal ( x:= (-1)^sgn * 10^exp * SigDig )
INT sgn \ sign; 0=pos, 256=neg
INT exp \ as if decimal point were to the right of SigDig
22 BYTES SigDig \ to fake string[20] ; 22 to make even
\ SANE Record DecForm
INT style \ Float=0; Fixed=256
INT digits \ # of sig digits,if float; # dec. places,if fixed.
string floater \ to hold formatted output string
string expStr \ to hold formatted exponent string
var places \ number of places to right of dec. pt.
int index
( -- )
:M CLEAR: addr: sgn 26 erase unlock: floater clear: floater clear: expstr ;M
( -- ) \ Initialize strings etc.
:M INIT: new: floater new: expStr clear: self ;M
( -- )
:M EINIT: clear: self FloatDecimal put: style ( 19 put: digits) ;M
( -- ) \ Initialize for fixed conversion
:M FINIT: clear: self FixedDecimal put: style ;M
( -- ) \ Puts a zero in decimal record
:M ZERO: clear: self $ 0130 addr: sigDig w! ;M
( -- float ) \ ==== attempt to convert decimal to a float;
:M DEC2FLOAT: { \ flt -- flt }
abs: sgn \ Addr of decimal record
new: fltMem -> flt flt 2+ +base \ Absolute Destination address
$ 0009 \ FFEXT FOD2B + -- Opcode for decimal to binary; dest=extended
fp68k flt \ Call FP68K
;M
( float -- ) \ ==== convert float to decimal ==== \
:M FLOAT2DEC: { flt -- }
abs: style \ Absolute Addr of Decform record
flt 2+ +base \ Absolute Addr of source
abs: sgn \ Absolute Addr of Decimal record
$ 000b \ FFEXT FOB2D + -- Opcode for binary to decimal; source=extended
fp68k flt fdrop \ Call FP68K, dispose of float
\ addr: sigDig 1+ c@ ascii 0 =
\ IF clear: exp THEN
;M
( -- ) \ Set up float for in decimal record in scientific format,
\ left-justified in a field of width characters.
:M num2dec: float2dec: self
abs: style (abs) pad +base call dec2str
pad count put: floater ;M
:M ROUND: ( f -- f') 1 swap 0 do 10 * LOOP >float fdup >r f* round r> f/ ;M
( flt width -- addr len)
:M GETEText: { width \ pos -- addr len }
einit: self
num2dec: self
start: floater ascii e charof: floater
IF drop size: floater substr: floater put: expStr
width size: expStr - 3 max \ bl or -, digit, decimal minimum
size: floater size: expStr - min -> pos \ keep at least 2 numbers for decimal
pos moveto: floater \ round up NEED
size: floater substr: floater get: expStr replace: floater
ELSE addr: sigDig count drop c@
dup ascii I = IF pad 1+ 1 put: floater
" Infinity" add: floater
width 10 - 0 DO bl +: floater LOOP
THEN
ascii N = IF pad 1+ 1 put: floater width 14 >
IF " Not a number " add: floater
width 14 -
ELSE " NaN " add: floater
width 5 -
THEN
0 DO bl +: floater LOOP
THEN
THEN lock: floater get: floater ;M
:M EPRINT: geteText: self type ;M
\ Carry out f.r
:M GETFText: { width decimal \ dot -- addr len }
finit: self
decimal round: self num2dec: self
start: floater ascii . charof: floater
IF -> dot
decimal abs 1+ subStr: floater put: expStr
get: sgn not IF start: floater bl pad c! pad 1 insert: floater 1 ++> dot THEN
dot moveto: floater
size: floater substr: floater get: expStr replace: floater
size: floater width <
IF bl width size: floater - fill: expStr
start: floater get: expStr insert: floater
THEN
ELSE addr: sigDig count drop c@
dup ascii I = IF get: sgn
IF ascii - ELSE bl THEN pad c! pad 1 put: floater
" Infinity" add: floater
width 10 - 0 DO bl +: floater LOOP
THEN
ascii N = IF get: sgn
IF ascii - ELSE bl THEN pad c! pad 1 put: floater
width 14 >
IF " Not a number " add: floater width 14 -
ELSE " NaN " add: floater width 5 -
THEN 0 DO bl +: floater LOOP
THEN
THEN lock: floater get: floater ;M
:M FPRINT: getFText: self type ;M
:M SCAN: ( addr len --) str255 -base dup c@ 2+ padbl
buf255 +base 1+ clear: index abs: index (abs) valid? 3+ +base
call PStr2Dec ;M
:M CONV?: { addr len -- b } addr len scan: self get: index len = ;M
\ str255 format at addr
:M ATOF: ( addr -- f t | f )
count conv?: self IF dec2float: self true ELSE false THEN ;M
:M classinit: 19 put: digits ;M
;Class
fpi/o floati/o \ The default fpi/o object
init: floati/o
( width -- )
( flt -- ) \ Print a float in scientific format in a field of width chars.
: e.r ( flt width -- ) eprint: floati/o ;
( flt -- ) \ Print a float in scientific format.
: e. 26 e.r ;
( addr len -- fval T ) \ Successful \ Converts a relative str255 string
( addr len -- F ) \ Unsuccessful \ into a floating point number.
: atof ( addr len -- f t | f )
str255 -base atof: floati/o ;
( flt width decimal -- ) \ Print a float without exponents, in a field of
\ width wide and of decimal places
: f.r ( flt width decimal -- ) fprint: floati/o ;
\ testing
\ int index
\ 0 variable valid?
\ : scan str255 -base dup c@ 2+ padbl
\ buf255 +base 1+ clear: index abs: index abs: floati/o valid? 3+ +base call PStr2Dec ;
\ : conv { addr len -- f t | f } addr len scan get: index len = ;
\ : sgn floati/o get: int ;
\ : exp floati/o 2+ get: int ;
\ : sigdig floati/o 4+ count type ;
\ : style floati/o 26 + get: int ;
\ : digits floati/o 28 + get: int ;
\ floati/o 30 + @ string floater floater !
\ floati/o 38 + @ string expStr expStr !
\ : places floati/o 46 + get: var ;